/*
 * 文件名：bsp_sdcard.cpp
 * 功能描述：SD卡操作和文件管理
 */
#include <Arduino.h>
#include "config.h"
#include "bsp_ble.h"
#include "bsp_motor.h"
#include "bsp_sdcard.h"

ArduinoOutStream cout(Serial);
SdFile file;
SdFile dir;
SdFat sd;

char pwd_path[] = "/";
const uint16_t NAME_LENGTH = 50;
const uint16_t LINE_LENGTH = 50;
char pathname_arr[20][NAME_LENGTH] = {};
bool center_start = true;
// Position of file's directory entry.
uint16_t saved_dirIndex[20];
uint16_t saved_idx = 0;

bool hasSuffix(const char *str, const char *suffix)
{
    if (!str || !suffix)
        return false;
    uint8_t lenStr = strlen(str);
    uint8_t lenSuffix = strlen(suffix);
    if (lenSuffix > lenStr)
        return false;
    return strncmp(str + lenStr - lenSuffix, suffix, lenSuffix) == 0;
}

//// 计数\n的个数, 虽然不准但很快
long countLines(SdFile *file)
{
    long numLines = 0;
    while (file->available())
    {
        if (file->read() == '\n')
        {
            numLines++;
        }
    }
    file->rewind();
    return numLines;
}

void sdInit()
{
    //------------------------------------------------------------------------------
    SPI.begin(SD_CLK_PIN, SD_MISO_PIN, SD_MOSI_PIN, SD_CS_PIN); // CLK, MISO, MOSI, CS
                                                                //    SPI.begin(12, 13, 11, 10); // CLK, MISO, MOSI, CS

    if (!sd.begin(SD_CS_PIN, SD_SCK_MHZ(16)))
    {
        sd.initErrorHalt();
    }
    Serial.println("Sd card init done.");

    //// 打印全部目录
    //    Serial.printf("File List_____________________________\n");
    //    sd.ls(LS_R);
    //    Serial.printf("_____________________________\n");

    //------------------------------------------------------------------------------
    //    Serial.printf("File Size_____________________________\n");
    //    if (!dir.open(pwd_path))
    //    {
    //        sd.errorHalt("open root failed");
    //    }
    //    while (file.openNext(&dir, O_RDONLY))
    //    { //// 通过OpenNext 打开下一个文件
    //        if (!file.isSubDir() && !file.isHidden())
    //        { // Skip directories and hidden files.
    //            //            file.printFileSize(&Serial);////使用Serial.write打印
    //            // 打印file.fileSize(), 如果小于1000,则尾缀B; 大于1000小于1000000,则除以1000,尾缀KB, 大于1000000,除以1000000,尾缀MB
    //            if (file.fileSize() < 1000)
    //            {
    //                Serial.printf("%6d B  \t", file.fileSize());
    //            }
    //            else if (file.fileSize() < 1000000)
    //            {
    //                // 设置printf右对齐,浮点数一共6位,少的左边用空格补齐
    //                Serial.printf("%6.2f KB\t", file.fileSize() / 1000.0);
    //            }
    //            else
    //            {
    //                Serial.printf("%6.2f MB\t", file.fileSize() / 1000000.0);
    //            }
    //            //            Serial.write(' ');
    //            file.printModifyDateTime(&Serial);
    //            Serial.write(' ');
    //            Serial.printf("%d", file.dirIndex());
    //            Serial.write(' ');
    //            file.printName(&Serial);
    //            if (file.isDir())
    //            { ////文件夹用/结尾
    //                // Indicate a directory.
    //                Serial.write('/');
    //            }
    //            Serial.println();
    //        }
    //        file.close(); //// 因为while中open了,必须要close
    //    } //// 问题是只能遍历1个文件夹的1层
    //    dir.rewind(); // 重置
    //    dir.close();
    //    Serial.printf("_____________________________\n");

    // ------------------------------------------------------------------------------
    // 主要使用的文件列表打印过程
    //    Serial.printf("File Name,\t\tRows,\tTime Cost,\t DirIndex_____________________________\n");
    //    if (dir.open(pwd_path, O_RDONLY))
    //    { /// O_RDONLY 是 O_READ 的别名
    //        int tmp_i = 0;
    //        while (1)
    //        {
    //            // 计时 start_time
    //            unsigned long start_time = millis();
    //
    //            if (file.openNext(&dir, O_RDONLY))
    //            {
    //                if (!file.isHidden())
    //                { // Skip directories and hidden files.
    //                    char filename[NAME_LENGTH];
    //                    file.getName(filename, NAME_LENGTH);
    //
    //                    // 检查文件是否有特定尾缀
    //                    if (hasSuffix(filename, ".traj") or hasSuffix(filename, ".txt") or hasSuffix(filename, ".thr") or hasSuffix(filename, ".cmd"))
    //                    {
    //
    //                        tmp_i++;
    //                        Serial.printf("%d,%-16s", tmp_i, filename);
    //
    //                        //// 行计数
    //                        long lineCount = countLines(&file);
    //                        Serial.printf(",\t%ld,\t", lineCount);
    //
    //                        //// 记录dirIndex
    //                        saved_dirIndex[saved_idx] = file.dirIndex();
    //                        // 将filename 复制到 pathname_arr[saved_idx]
    //                        strcpy(pathname_arr[saved_idx], filename);
    //
    //                        ++saved_idx;
    //                        unsigned long time_used = millis() - start_time;
    //                        Serial.printf("%d ms,\t", time_used);
    //
    //                        Serial.printf("\tdirIndex[%d]\n", file.dirIndex());
    //                    }
    //                }
    //                file.close();
    //            }
    //            else
    //            {
    //                break;
    //            }
    //        }
    //    }
    dir.rewind(); // 重置
    dir.close();
    //    Serial.printf("_____________________________\n");

    //    cout << "\nDone!\n";

    // 打印记录的文件index
    //    for (int i = 0; i < saved_idx; ++i) {
    //        Serial.printf("[%d]->%d,",i,saved_dirIndex[i]);
    //        Serial.println(pathname_arr[i]);
    //    }
    //------------------------------------------------------------------------------
}

void sdRead()
{
    //	while(1);
    ////=================================================================================
    // 打印目录
    for (int i = 0; i < saved_idx; ++i)
    {
        Serial.printf("[%d]->%d,", i, saved_dirIndex[i]);
        Serial.println(pathname_arr[i]);
    }
    // 打开目录(必须)
    if (!dir.open(pwd_path))
    {
        sd.errorHalt("open root failed");
    }
    file.rewind();

    ////  Wait for USB Serial 读取编号, 清除之前的
    do
    {
        delay(5);
    } while (Serial.available() && Serial.read() >= 0);

    /// 以下用于读取连续数字
    int c;
    String received = "";
    Serial.print(F("\r\nEnter File Numbers: "));
    while (true)
    {
        while (!Serial.available())
        {
            SysCall::yield();
        }
        c = Serial.read();
        if (c == '\n' || c == '\r')
        {
            break;
        }
        if (!isdigit(c))
        {
            Serial.println(F("Invalid character, only numbers are allowed"));
            received = "";
            continue;
        }

        received += String((char)c);
    }
    delay(5); // 这个延迟是必要的，特别是如果你使用的是软件串行。
    int cur_file_idx = received.toInt();

    Serial.println(cur_file_idx);
    Serial.printf("Opening [%d],", saved_dirIndex[cur_file_idx]);
    Serial.printf("As File: %s\n", pathname_arr[cur_file_idx]);
}